 
from kubernetes import client,config
from kubernetes.client.rest import ApiException

import boto3
import logging
import base64
from botocore.signers import RequestSigner
import re

import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
ENV = 'preprod'
if ENV == 'prod':
    PROFILE_NAME='a206097prod'

    CLUSTER_NAME='a206097-prod-search-searchsip'
    REGION="us-east-1"
    IMAGE_NAME ="889200086195.dkr.ecr.us-east-1.amazonaws.com/a206097-logstash-opensearch:8.9.0.2"
    jobEnvDict = {
               "PIPELINE_STATE_TABLE":'a206097-prod-search-sip-selfservice-pipeline-state',
               "SECOND_LEVEL_SQS_QUEUEURL":'https://sqs.us-east-1.amazonaws.com/889200086195/a206097-prod-us-east-1-search-sip-logstash-queue.fifo'
            }
    
elif (ENV == 'preprod'):
    PROFILE_NAME='edp-core-sdlc-preprod'

    CLUSTER_NAME='a206097-preprod-search-searchsip'
    REGION="us-east-1"
    IMAGE_NAME ="318935743692.dkr.ecr.us-east-1.amazonaws.com/a206097-logstash-opensearch:8.9.0.2"
    jobEnvDict = {
               "PIPELINE_STATE_TABLE":'a206097-preprod-search-sip-selfservice-pipeline-state',
               "SECOND_LEVEL_SQS_QUEUEURL":'https://sqs.us-east-1.amazonaws.com/318935743692/a206097-preprod-us-east-1-search-sip-logstash-queue.fifo'
            }
else:
   print("do nothing")
   exit(0)

def get_bearer_token(session, cluster_id, region):
    STS_TOKEN_EXPIRES_IN = 60
  
    client = session.client("sts",region_name=region) 
    service_id = client.meta.service_model.service_id
    signer = RequestSigner(
        service_id,
        region,
        'sts',
        'v4',
        session.get_credentials(),
        session.events  
    )

    params = {
        'method': 'GET',
        'url': 'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'.format(region)  ,
        'body': {},
        'headers': {
            'x-k8s-aws-id': cluster_id
        },
        'context': {}
    }

    signed_url = signer.generate_presigned_url(
        params,
        region_name=region,
        expires_in=STS_TOKEN_EXPIRES_IN,
        operation_name=''
    )

    base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8')

    # remove any base64 encoding padding:
    return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)


def generate_kubeconfig(eks_cluster,eks_region,eks_api):
    # Get clusterInfo from EKS API
    cluster_info = eks_api.describe_cluster(name=eks_cluster)

    certificate  = cluster_info['cluster']['certificateAuthority']['data']
    endpoint     = cluster_info['cluster']['endpoint']

    logger.info('The API endpoint of EKS cluster ' + eks_cluster + ' is ' + endpoint)

    # Generating kubernetes config
    kube_config = dict()

    kube_config['apiVersion'] = 'v1'
    kube_config['clusters'] = [
        {
            'cluster':
                {
                    'server': endpoint,
                    'certificate-authority-data': certificate
                },
            'name': eks_cluster

        }
    ]

    kube_config['contexts'] = [
        {
            'context':
                {
                    'cluster': eks_cluster,
                    'user': 'admin'
                },
            'name': eks_cluster
        }]

    kube_config['current-context'] = eks_cluster
    kube_config['Kind'] = 'config'
    kube_config['users'] = [
        {
            'name': 'admin',
            'user': {
                'exec': {
                    'apiVersion': 'client.authentication.k8s.io/v1alpha1',
                    'args': [
                        '--region',
                        eks_region,
                        'eks',
                        'get-token',
                        '--cluster-name',
                        eks_cluster
                    ],
                    'command': 'aws'
                }
            }
        }]

    return kube_config



def get_apiClientConfiguration(profile_name, eks_cluster, eks_region):
    # Configure
    session = boto3.Session(profile_name = profile_name)

    # Get clusterInfo from EKS API
    eks_api      = session.client('eks', region_name=eks_region)
    cluster_info = eks_api.describe_cluster(name=eks_cluster)
    eks_api_server     = cluster_info['cluster']['endpoint']

    conf_dict     = generate_kubeconfig(eks_cluster, eks_region,eks_api)

    #configs= client.Configuration()
    #configs.host   = "https://46B2F0F08D52D8A4A0BE49B57F9B1135.sk1.us-east-1.eks.amazonaws.com"

    #authentication always happens with below header Bearer + token
    #configs.api_key = {"authorization": "Bearer " + get_bearer_token('a206097-preprod-search-searchsip', 'us-east-1')}
    #client.Configuration.set_default(configs)

   
    #config.load_kube_config(config_file= "C:\\Users\\U6064508\\.kube\\config")
    config.load_kube_config_from_dict(conf_dict)

    configuration = client.Configuration()
    configuration.host   = eks_api_server
    token = get_bearer_token(session, eks_cluster,eks_region)
    
    
    configuration.api_key['authorization'] = token
    configuration.api_key_prefix['authorization'] = 'Bearer'    
    configuration.verify_ssl = False
    #configuration.debug = True
    return configuration

def update_deployment(api, 
                      deployment,
                      image, 
                      jobEnvDict, 
                      namespace = 'a206097-logstash'):
    # Update container image
    deployment.spec.template.spec.containers[0].image = image
    deployment.spec.template.spec.containers[0].imagePullPolicy = 'Always'

    # if len(jobEnvDict) > 0:
    #   for key  in jobEnvDict:
    #     deployment.spec.template.spec.containers[0].env.append( client.V1EnvVar(name=key,value=jobEnvDict[key]) )
    if len(jobEnvDict) > 0:
        #envs = deployment.spec.template.spec.containers[0].env
        
        for key  in jobEnvDict:
            deployment.spec.template.spec.containers[0].env.append( client.V1EnvVar(name=key,value=jobEnvDict[key]) )

    # patch the deployment

    try :
        resp = api.patch_namespaced_deployment(
            name=deployment.metadata.name, namespace=namespace, body=deployment
        )
        print("\n[INFO] deployment's container image updated.\n")
        print("%s\t%s\t\t\t%s\t%s" % ("NAMESPACE", "NAME", "REVISION", "IMAGE"))
        print(
            "%s\t\t%s\t%s\t\t%s\n"
            % (
                resp.metadata.namespace,
                resp.metadata.name,
                resp.metadata.generation,
                resp.spec.template.spec.containers[0].image,
            )
        )        
    except ApiException as e:
        print("Exception when calling AppsV1Api->patch_namespaced_deployment: %s\n" % e)


configuration = get_apiClientConfiguration(PROFILE_NAME,CLUSTER_NAME,REGION)


with client.ApiClient(configuration) as api_client:
  kube_client = client.AppsV1Api(api_client)
  resp = kube_client.list_namespaced_deployment(namespace="a206097-logstash")
  for deployment in resp.items:
    print(deployment.metadata.name)
    if (deployment.metadata.name.startswith("pod-")):
      update_deployment(kube_client,deployment,IMAGE_NAME,jobEnvDict)   
